﻿/* ######################################## *\
 * ### Copyright (C) 2009 AJ Ravindiran ### *
 * ### HTTP://THEAJ.NET/ <AJ@THEAJ.NET> ### *
\* ######################################## */
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Configuration;

using AJRavindiran.Jolt.Network;
using AJRavindiran.Jolt.Storage;
using AJRavindiran.Jolt.Utilities;
using AJRavindiran.Jolt.Utilities.Logging;
using AJRavindiran.Jolt.Utilities.Parsing;

namespace AJRavindiran.Jolt
{
    public static class JoltEnvironment
    {
        #region Fields
        private static Logger mLogger = new Logger();

        private static XML mXML = new XML();
        private static INI mINI = new INI();

        private static Configuration mConfiguration;
        private static DatabaseManager mDatabaseManager;
        private static TCPConnection mTCPConnection;
        private static RuneScape.RuneScape mRuneScape;

        private static Thread mMonitor = new Thread(new ThreadStart(monitor));
        #endregion

        #region Properties
        /// <summary>
        /// Gets the XML Reader.
        /// </summary>
        public static XML XML
        {
            get { return mXML; }
        }

        /// <summary>
        /// Gets the INI reader.
        /// </summary>
        public static INI INI
        {
            get { return mINI; }
        }

        /// <summary>
        /// Gets if JoltEnvironment is in debug mode.
        /// </summary>
        public static bool DebugMode
        {
            get { return Program.DebugMode; }
        }

        /// <summary>
        /// Gets if Errors should be shown with a beep.
        /// </summary>
        public static bool BeepEnabled
        {
            get { return Program.BeepEnabled; }
        }

        /// <summary>
        /// Property for Configuration. Can now be used to get configs from file.
        /// <code>Configuration[key]</code>
        /// </summary>
        public static Configuration Configuration
        {
            get { return mConfiguration; }
        }
        #endregion

        #region Methods
        public static void Initialize()
        {
            // If we are indebug mode, we will show advanced 
            //functions and settings to help solve problems easier.
            if (DebugMode)
            {
                mLogger.WriteWarn("You are in debug mode. Some functions may differ.");
                mLogger.LogPriority = LogLevel.Debug;
            }
            else
            {
                mLogger.LogPriority = LogLevel.Info;
            }
            mLogger.WriteInfo("Jolt Environment is now booting up on your computer...");

            try
            {
                try
                {
                    mConfiguration = Configuration.LoadFromFile(@".\Bin\SETTINGS");
                }
                catch (FileNotFoundException e)
                {
                    mLogger.WriteError("We could not load any settings. " + e.Message);
                    ShutDown();
                    return;
                }

                #region Database Initialization
                DatabaseServer databaseServer = new DatabaseServer(
                    Configuration["database.host"],
                    Configuration.TryParseUInt32("database.port"),
                    Configuration["database.user"],
                    Configuration["database.pass"]);

                Database database = new Database(
                    Configuration["database.name"],
                    Configuration.TryParseUInt32("database.minpoolsize"),
                    Configuration.TryParseUInt32("database.maxpoolsize"));

                mDatabaseManager = new DatabaseManager(databaseServer, database);
                mDatabaseManager.SetClientAmount(2);
                mDatabaseManager.ReleaseClient(mDatabaseManager.GetClient().Handle);
                mDatabaseManager.StartMonitor();
                #endregion

                #region Connection Initialization
                mTCPConnection = new TCPConnection(
                    Configuration.TryParseInt32("net.game_socket.port"),
                    Configuration.TryParseInt32("net.game_socket.maxcon"));
                #endregion

                // Start a thread on lowest priority that will
                // update the title with the latest GC memory size.
                mMonitor.Priority = ThreadPriority.Lowest;
                mMonitor.Start();

                // If this message has been reached, the server was successfully setup correctly.
                mLogger.WriteClean("Successfully booted Jolt Environment!");
                mLogger.WriteBlank();

                // Startup RuneScape Emulator.
                mRuneScape = new RuneScape.RuneScape();
            }
            catch (Exception ex)
            {
                mLogger.WriteException(ex);
            }
        }

        public static void ShutDown()
        {
            mLogger.WriteInfo("Jolt Environment is cleaning up for shut down...");

            // If the server is alive, we'll close it.
            // We'll set the title to something else because
            // it will be stuck on that last memory print.
            if (mMonitor.IsAlive)
                mMonitor.Abort();
            Console.Title = "Jolt Environment: RuneScape Emuatlor - Shutdown";

            if (GetRuneScape() != null)
            {
                mLogger.WriteInfo("Destroying RuneScape Emulator...");
                GetRuneScape().ShutDown();
            }

            // Shutdown the database safely.
            if (GetDatabase() != null)
            {
                mLogger.WriteInfo("Destroying database " + GetDatabase().ToString() + "...");
                GetDatabase().StopMonitor();
                GetDatabase().DestroyClients();
                GetDatabase().DestroyManager();
            }

            // Shutdown the tcp connecion safely.
            if (GetTCPConnection() != null)
            {
                mLogger.WriteInfo("Destroying TCP connection...");
                GetTCPConnection().ShutDown();
            }

            /// Wait for user to press a key.
            /// Then we exit the environment.
            JoltEnvironment.GetLogger().WriteClean("Successfully shut down. Press any key to exit...");
            Console.ReadKey();
            System.Environment.Exit(0);
        }

        private static void monitor()
        {
            while (true)
            {
                long memoryUsage = GC.GetTotalMemory(false) / 1024;
                Console.Title = "Jolt Environment: RuneScape Emulator [Garbage Collection: " + memoryUsage + "KB]";
                Thread.Sleep(1000);
            }
        }

        public static RuneScape.RuneScape GetRuneScape()
        {
            return mRuneScape;
        }

        public static Logger GetLogger()
        {
            return mLogger;
        }

        public static DatabaseManager GetDatabase()
        {
            return mDatabaseManager;
        }

        public static TCPConnection GetTCPConnection()
        {
            return mTCPConnection;
        }
        #endregion
    }
}
